#!/usr/bin/perl
use strict;
use Getopt::Long;

use constant MARGIN_MULTIPLIER => 10000;
use constant MARGIN_CS_MULTIPLIER => 100;
use constant LONGSHORT_SCALE => 1000000;
use constant PNL_SCALE => 1000000;

#display standard yearly statistics from pnl file

my ($p, $t, $f, $sdate, $edate, $booksize) = (undef, "yearly", "short",-1,-1,-1);
GetOptions(
  "p=s" => \$p,	
  "t=s" => \$t,	
  "f=s" => \$f,	
  "s=i" => \$sdate,	
  "e=i" => \$edate,	
  "b=i" => \$booksize,	
);

if(!defined $p) {
  if($#ARGV <0){
    die "Usage: simsummary.pl pnl_file\n";
  } else {
    $p = shift @ARGV;
  }
}

my $DD_start =0;
my $DD_setst =0; 
my $DD_sum =0; 

my $XX_last =0;
my $ldate   =0;

my @lastline = split('\t',qx(tail -n1 $p));
my $srecent = $lastline[0] - 20000;
my %stats =();

sub doStats($$$$$$$$) {
  my $XX = shift;
  my ($date, $pnl, $long, $short, $return, $sh_hld, $sh_trd, $b_share, $t_share) = @_;
  push @{$stats{$XX}{dates}}, $date;
  my $curr_ret = ($booksize >0 ) ? ($pnl/$booksize *2):$return;

  $stats{$XX}{pnl}  += $pnl;
  $stats{$XX}{long}  += $long;
  $stats{$XX}{short}  += $short;
  $stats{$XX}{sh_hld}  += $sh_hld;
  $stats{$XX}{sh_trd}  += $sh_trd;
  $stats{$XX}{avg_ret}  += $curr_ret;

  $stats{$XX}{b_sh}  += $b_share;
  $stats{$XX}{t_sh}  += $t_share;

  if($long !=0 || $short!=0 || $booksize>0){
    $stats{$XX}{days}++;  
  }


  $stats{$XX}{xsy} += $curr_ret;  
  $stats{$XX}{xsyy} += $curr_ret*$curr_ret;  


  $stats{$XX}{up_days} ++ if ($pnl > 0);  

  if(!exists $stats{$XX}{mm_sum}) {
    $stats{$XX}{mm_sum} =0;
    $stats{$XX}{mm_cnt} =0;
    $stats{$XX}{up_months} =0;
  }

  if(!exists $stats{$XX}{ww_sum}) {
    $stats{$XX}{ww_sum} =0;
    $stats{$XX}{ww_cnt} =0;
    $stats{$XX}{up_weeks} =0;
  }

  if(!exists $stats{$XX}{drawdown}) {
    $stats{$XX}{drawdown} =0;
    $stats{$XX}{dd_start} =0;
    $stats{$XX}{dd_end} =0;
  }

}

my %finalTimeHash =();
my %goodLong =();
my %goodShort =();

sub canUpdate($$$)
{
  my $date = shift;
  my $long = shift;
  my $short = shift;
  if(!exists $goodLong{$date} || !exists $goodShort{$date} ){
    return 1;
  } else {
      my $curr_diff = abs(abs($long) + abs($short) - $booksize );
      my $target_diff = abs(abs($goodLong{$date}) + abs($goodShort{$date}) - $booksize);
      if($curr_diff <= $target_diff) {return 1;}
  }
  return 0;

}

open(F,$p) or die $!;
while(<F>) {
  chomp;
  my ($date, $pnl, $long, $short) = split;
  last if (length($date)<9);
  my $date_ = substr($date,0,8);
  $finalTimeHash{$date_}= $date; #overwrite
  if($booksize>0 && canUpdate($date_,$long,$short)>0){
    $goodLong{$date_}=$long;
    $goodShort{$date_}=$short;
  }
}
close(F);


open(F,$p) or die $!;
while(my $l = <F>) {
  chomp $l;
  my ($date, $pnl, $long, $short, $return, $sh_hld, $sh_trd, $b_share, $t_share) = split(/\s+/,$l);
  my $date_ = substr($date,0,8);
  next if (($sdate>0 && $date_<$sdate) || ($edate>0 && $date_>$edate));  
  next if (exists $finalTimeHash{$date_} && $date ne $finalTimeHash{$date_});
  $date = substr($date, 0, 8);
  
  my $XX = substr($date, 0, 4);
  if($t eq "monthly"){
    $XX = substr($date, 0, 6);
  }

  $long = ($booksize>0) ? $goodLong{$date_} : $long;
  $short = ($booksize>0) ? $goodShort{$date_} : $short;

  &doStats($XX, $date,$pnl,$long,$short, $return, $sh_hld, $sh_trd, $b_share, $t_share);
  &doStats("ALL", $date,$pnl,$long,$short, $return, $sh_hld, $sh_trd, $b_share, $t_share);

  if($date > $srecent){
    &doStats("RECENT", $date,$pnl,$long,$short, $return, $sh_hld, $sh_trd, $b_share, $t_share);
  }
  
  #drawdowns
  if($DD_setst){
    $DD_start=$date;
    $DD_setst=0;
  }
  $DD_sum += $pnl;
  if($DD_sum>=0) {
    $DD_sum =0;
    $DD_start = $date;
    $DD_setst =1;
  }

  if($DD_sum < $stats{$XX}{drawdown}) {
    $stats{$XX}{drawdown} = $DD_sum;
    $stats{$XX}{dd_start} = $DD_start;
    $stats{$XX}{dd_end}   = $date;
  }

  if($DD_sum < $stats{ALL}{drawdown}) {
    $stats{ALL}{drawdown} = $DD_sum;
    $stats{ALL}{dd_start} = $DD_start;
    $stats{ALL}{dd_end}   = $date;
  }

  if($date > $srecent && $DD_sum < $stats{RECENT}{drawdown}) {
    $stats{RECENT}{drawdown} = $DD_sum;
    $stats{RECENT}{dd_start} = $DD_start;
    $stats{RECENT}{dd_end}   = $date;
  }
  
  $ldate = $date;
  $XX_last =$XX;
}
close(F);

if ($f =~ /long/i) {
  printf ("%17s %7s %8s %7s %7s %7s %14s %7s %7s %7s %7s %7s %7s %7s %7s\n",
		"dates","long(M)","short(M)","pnl(M)","%ret","%tvr","shrp(IR)","%dd","%win","up_days","up_weeks","up_months","bpmrgn","csmrgn","fitness");

}
else {
  printf ("%17s %7s %8s %7s %7s %7s %14s %5s %5s %6s %6s %7s\n",
		"dates","long(M)","short(M)","pnl(M)","%ret","%tvr","shrp(IR)","%dd","%win","bpmrgn","csmrgn","fitness");
}

foreach my $XX (sort keys %stats) {
  printf("\n") if ($XX =~ m/ALL/);

  my $d = $stats{$XX}{days};
  if(defined $d && $d>0) {
    my $long = $stats{$XX}{long} / $d;
    my $short = $stats{$XX}{short} / $d;
    my $return = $stats{$XX}{avg_ret} / $d*250.;
    my $perwin = $stats{$XX}{up_days} / $d*100.;
    my $turnover = ($booksize > 0) ? $stats{$XX}{sh_trd} / $booksize / $d 
    : ($stats{$XX}{sh_hld} > 0 ? $stats{$XX}{sh_trd} / $stats{$XX}{sh_hld} :0 );
    my $drawdown = $long >0 ? $stats{$XX}{drawdown} / $long * -100 : 0 ; # percent of long side

    my $avg =0;
    my $std =0;
    my $ir =0;

    $avg = $stats{$XX}{xsy} / $d if ($d > 0);
    $std = sqrt( 1/ ($d -1) * ($stats{$XX}{xsyy} - $stats{$XX}{xsy} * $stats{$XX}{xsy} / $d )) if ($d>2);

    $ir = $avg / $std if ($std > 0);
    
    my $fitness = $turnover > 0 ? $ir/$turnover :0 ;

    my $printIr = sprintf("%0.3f(%0.3f)",$ir*sqrt(252), $ir);

    #calc margin
    my $margin = $stats{$XX}{sh_trd}!=0 ? MARGIN_MULTIPLIER * $stats{$XX}{pnl}/$stats{$XX}{sh_trd}:"NaN";  
    my $margin_cs = $stats{$XX}{t_sh}!=0 ? MARGIN_CS_MULTIPLIER * $stats{$XX}{pnl}/$stats{$XX}{t_sh}:"NaN"; 

 
    if ($f =~ /long/i) {
      printf ("%8d-%8d %7.2f %8.2f %7.3f %7.2f %7.2f %14s %7.2f %7.2f %7d %7.2f %7.3f %7.3f\n",
	$stats{$XX}{dates}[0],$stats{$XX}{dates}[-1],$long*1.0/+LONGSHORT_SCALE, $short*1.0/+LONGSHORT_SCALE, $stats{$XX}{pnl}*1.0/PNL_SCALE, $return*100,$turnover*100,$printIr, $drawdown, $perwin, $stats{$XX}{up_days},$stats{$XX}{up_weeks},$stats{$XX}{up_months},$margin,$margin_cs,$ir*sqrt(252)*sqrt(abs($return)/$turnover));
    }
    else {
      printf ("%8d-%8d %7.2f %8.2f %7.3f %7.2f %7.2f %14s %5.2f %5.2f %6.2f %6.3f %7.3f\n",
	$stats{$XX}{dates}[0],$stats{$XX}{dates}[-1],$long*1.0/+LONGSHORT_SCALE, $short*1.0/+LONGSHORT_SCALE, $stats{$XX}{pnl}*1.0/PNL_SCALE, $return*100,$turnover*100,$printIr, $drawdown, $perwin, $margin,$margin_cs,$ir*sqrt(252)*sqrt(abs($return)/$turnover));
        
    }
}
}
